<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数作用域(funciotn scope)</title>
  <!-- 
  在JavaScript中，函数作用域（Function Scope）是指在函数内部定义的变量的可访问范围。理解函数作用域对于编写高质量的JavaScript代码至关重要。

  一、作用域的概念
  作用域是指变量和函数的可访问范围。在JavaScript中，作用域分为全局作用域和局部作用域：
    1. 全局作用域：在代码的任何地方都可以访问的变量和函数。
    2. 局部作用域：在函数内部定义的变量和函数，只能在该函数内部访问。

  二、函数作用域
  在JavaScript中，每当定义一个函数时，都会创建一个新的作用域。函数内部的变量和参数在该函数外部是不可见的。

    function myFunction() {
      let localVar = "I am local"; // 局部变量
      console.log(localVar); // 可以访问局部变量
    }
    myFunction(); // 输出 "I am local"
    console.log(localVar); // 报错，localVar在外部不可访问

  三、变量提升（Hoisting）
  在函数作用域内，变量的声明会被提升到函数的顶部。这意味着即使在变量声明之前使用它，JavaScript也不会报错，但会返回 `undefined` 。

    function hoistingExample() {
      console.log(hoistedVar); // 输出 undefined
      var hoistedVar = "I am hoisted";
      console.log(hoistedVar); // 输出 "I am hoisted"
    }
    hoistingExample();

  四、函数参数
  函数的参数在函数内部也是局部变量，可以在函数体内访问。
    function greet(name) {
      console.log("Hello, " + name);
    }

    greet("Alice"); // 输出 "Hello, Alice"
    console.log(name); // 报错，name在外部不可访问

  五、嵌套函数
  在一个函数内部定义的函数称为嵌套函数。嵌套函数可以访问其外部函数的变量和参数。

    function outerFunction() {
      let outerVar = "I am outside";
      function innerFunction() {
          console.log(outerVar); // 可以访问外部函数的变量
      }

      innerFunction(); // 输出 "I am outside"
    }
    outerFunction();

  六、总结
  - 函数作用域是指在函数内部定义的变量和参数的可访问范围。
  - 函数内部的变量在外部不可访问，形成了局部作用域。
  - 变量提升（hoisting）意味着变量的声明会被提升到函数顶部，但赋值不会。
  - 函数参数在函数内部是局部变量，可以在函数体内使用。
  - 嵌套函数可以访问外部函数的变量和参数。
  
  -->
</head>
<body>

  <script>
    // 1. 函数作用域的理解
    // 函数作用域是指在函数内部定义的变量和参数的可访问范围。
    // 函数内部的变量在外部不可访问，形成了局部作用域。
    function myFunction() {
      // console.log("1. 函数作用域的理解", localVar); // 报错 ReferenceError: Cannot access 'localVar' before initialization
      let localVar = "I am inside the function";
      console.log("1. 函数作用域的理解", localVar); // 输出 "I am inside the function"
    }
    myFunction();
    // console.log(localVar); // 报错，localVar在外部不可访问

    // 2. 变量提升（Hoisting）
    // 变量提升（hoisting）意味着变量的声明会被提升到函数顶部，但赋值不会。
    function hoistingFunction() {
      console.log("2. 变量提升（Hoisting）", localVar); // 输出 "undefined"
      var localVar = "I am inside the function";
      console.log("2. 变量提升（Hoisting）", localVar); // 输出 "I am inside the function"
    }
    hoistingFunction();

    // 3. 函数参数是局部变量
    // 函数参数在函数内部是局部变量，可以在函数体内使用。
    function parameterFunction(param) {
      console.log("3. 函数参数是局部变量", param); // 输出传入的参数值
    }
    parameterFunction("Hello, World!");

    // 4. 嵌套函数可以访问外部函数的变量和参数
    function outerFunction() {
      let outerVar = "I am in the outer function";
      function innerFunction() {
        console.log("4. 嵌套函数可以访问外部函数的变量和参数", outerVar); // 输出 "I am in the outer function"
      }
      innerFunction();
    }

    // 5. 全局作用域
    // 在函数外部声明的变量是全局变量，可以在整个脚本中访问。
    let globalVar = "I am a global variable";
    function globalFunction() {
      console.log("5. 全局作用域", globalVar); // 输出 "I am a global variable"
    }
    globalFunction();

    // 6. 块级作用域
    // 使用 let 和 const 声明的变量具有块级作用域，它们只在声明它们的代码块内可见。
    function blockScopeFunction() {
      if (true) {
        let blockVar = "I am inside the block";
        console.log("6. 块级作用域", blockVar); // 输出 "I am inside the block"
      }
      // console.log(blockVar); // ReferenceError: blockVar is not defined
    }
    blockScopeFunction();

    // 7. 作用域链
    // 当访问一个变量时，JavaScript 引擎会从当前作用域开始，逐级向上查找，直到找到该变量或到达全局作用域。
    function scopeChainFunction() {
      let scopeChainVar = "I am in the scope chain function";
      function nestedFunction() {
        console.log("7. 作用域链", scopeChainVar); // 输出 "I am in the scope chain function"
      }
      nestedFunction();
    }

    scopeChainFunction();


    
  </script>
  
</body>
</html>